package com.itouch.bracelet.bluetooth;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

import org.apache.http.impl.conn.Wire;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * 

* @ClassName: BluetoothSpp 

* @Description: TODO(蓝牙连接、数据发送。接收处理类) 

* @author sunshineHu hucx@itouch.com.cn

* @date 2015年1月15日 上午10:06:50 

*
 */
public class BluetoothSpp {

	/**
	 * Singleton
	 */
	private BluetoothSpp(){
	}
	
	private static volatile BluetoothSpp INSTANCE=null;

	//线程互斥锁，减少因在死循环上面的资源开销，其实wait好还是每次创建线程好已属于空间和效率的问题，线程的轮换是消耗资源 by sunshineHu
	//为了防止死锁的发生，每次wait设置了最长时间10-30s
	private final Object statusMutext=new Object();
	private final Object readMutext=new Object();
	private final Object writeMutext=new Object();
	
	
	//创建时双重检查，其实没必要，一般都会在ui线程中调用
	public static BluetoothSpp getInstance(){
		if(INSTANCE==null){
			synchronized (BluetoothSpp.class) {
				if(INSTANCE==null){
					INSTANCE=new BluetoothSpp();
				}
			}
		}
		return INSTANCE;
	}
	
	//adapter
	private BluetoothAdapter mBluetoothAdapter;
	//消息处理中心，ui线程
	private Handler mHandler;
	//socket的引用
	private volatile BluetoothSocket mBluetoothSocket;
	
	//2个数据处理线程
	private ReceiveThread receiveThread;
	private SendThread sendThread;
	
	//连接线程
	private ConnectThread connectThread;
	
	//检查连接状态线程
	private CheckThread checkThread;
	
	//蓝牙mac地址
	private String address;
	//上下文
	private Context mContext;
	
	private final int bufferSize=256;//缓冲区长度
	//设备
	private volatile BluetoothDevice device=null;
	
	//创建实例后要先绑定handler后才能进行接下来的调用
	public void setHandler(Handler h) {
		// TODO Auto-generated constructor stub
		mHandler=h;
	}
	
	
	@SuppressLint("NewApi")
	public synchronized void connect(String address,Context c){
		
		this.address=address;
		mContext=c;

		mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
		device = mBluetoothAdapter.getRemoteDevice(address);
        
		BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
		//如果蓝牙未打开返回
		if(!adapter.isEnabled()){
			return;
		}
		
		//系统大于kitkat可以隐藏提示，还没测试过，公司测试机都没有，唉。。。
		if(android.os.Build.VERSION.SDK_INT>=19){
			device.setPairingConfirmation(false);
		}
		
    	//蓝牙3.0
        //已绑定 未连接 已打开
        if(device.getBondState()==BluetoothDevice.BOND_BONDED&&BluetoothValue.INSTANCE.getConnectStatus()==BluetoothConstants.STATUS_UNCONNECTED&&BluetoothValue.INSTANCE.isBluetoothStatus()){
        	if(connectThread==null||!connectThread.isAlive()){
        		//已配对的设备并且未在连接，必须放在里面，connect 线程未结束但标记符号已改为unconnected，会导致标记符永远为connecting
            	BluetoothValue.INSTANCE.setConnectStatus(BluetoothConstants.STATUS_CONNECTING);//标记为连接中
            	
        		connectThread=new ConnectThread(device);
        		connectThread.setName("BluetoothConnectThread");
        		connectThread.start();//连接获取socket为阻塞。放在新线程中
        	}
        }else if(device.getBondState()==BluetoothDevice.BOND_NONE){
            try {
            	Message msg=mHandler.obtainMessage();
				msg.what=BluetoothConstants.MESSAGE_DEVICE_UNBOND;
				msg.sendToTarget();
            	
				Method creMethod = BluetoothDevice.class.getMethod("createBond");    
				creMethod.invoke(device);
				
				//device.createBond();
				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}    
        }
        
	}
	

	/**
	 * 检测连接是否存在
	 */
	public synchronized void checkConnect(){
		
		if(checkThread==null||!checkThread.isAlive()){
			checkThread=new CheckThread();
			checkThread.setName("BluetoothCheckThread");
			checkThread.start();//启动连接检查线程
			
		}
		
	}
	
	
	/**
	 * 断开连接
	 */
	public synchronized void disconnect(){
		
		if(!BluetoothValue.INSTANCE.disConnecting){
			//标记为正在断开
			BluetoothValue.INSTANCE.disConnecting=true;
			DisConnectThread disConnectThread=new DisConnectThread();
			disConnectThread.setName("BluetoothDisconnectThread");
			disConnectThread.start();
		}
		
	}
	
	
	class ConnectThread extends Thread{

		BluetoothDevice device;
		
		public ConnectThread(BluetoothDevice device) {
			// TODO Auto-generated constructor stub
			this.device=device;
		}
		
		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			try {
				//mBluetoothSocket = device.createRfcommSocketToServiceRecord(uuid);
				
				Method m = device.getClass().getMethod("createRfcommSocket",new Class[] { int.class });
				mBluetoothSocket = (BluetoothSocket) m.invoke(device, 1);
				
				mBluetoothSocket.connect();
				BluetoothValue.INSTANCE.setConnectStatus(BluetoothConstants.STATUS_CONNECTED);//标记为已连接
				Message msg=mHandler.obtainMessage();
				msg.what=BluetoothConstants.MESSAGE_CONNECT_SUCCESS;
				msg.sendToTarget();
				if(receiveThread==null||!receiveThread.isAlive()){
					receiveThread=new ReceiveThread();
					receiveThread.setPriority(NORM_PRIORITY);//优先级普通
					receiveThread.setName("BluetoothReceiveThread");
					receiveThread.start();//启动接收线程
				}
				if(sendThread==null||!sendThread.isAlive()){
					sendThread=new SendThread();
					sendThread.setPriority(NORM_PRIORITY);//优先级普通
					sendThread.setName("BluetoothSendThread");
					sendThread.start();//启动发送线程线程
				}
				
				//通知可以读了
				synchronized (readMutext) {
					readMutext.notify();
				}
				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				Message msg=mHandler.obtainMessage();
				msg.what=BluetoothConstants.MESSAGE_CONNECT_FAILED;
				msg.obj=e;
				msg.sendToTarget();
				BluetoothValue.INSTANCE.setConnectStatus(BluetoothConstants.STATUS_UNCONNECTED);//连接错误
				
				synchronized (statusMutext) {
					
					statusMutext.notify();
				
				}
				
				//log
				//Log.e("BluetoothConnect exception", e.getMessage());
				
			}   
		}
		
		
	};
	
	
	/**
	 * 关闭连接线程
	 * @author SunshineHu
	 *
	 */
	class DisConnectThread extends Thread{

		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();

			//消息包队列不为空
			int count =0;
			//最多等待10s
			while(BluetoothValue.INSTANCE.packetQueue.size()>0&&count<10){
				try{
				//休眠1秒再检测
					sleep(1000);
					count++;
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			//清空队列
			BluetoothValue.INSTANCE.packetQueue.clear();
			
			//蓝牙标记为关
			BluetoothValue.INSTANCE.setBluetoothStatus(false);
			
			//断开并标记为未连接
			if(mBluetoothSocket==null){
				BluetoothValue.INSTANCE.setConnectStatus(BluetoothConstants.STATUS_UNCONNECTED);
			}else{
				try {
					mBluetoothSocket.close();
					mBluetoothSocket=null;
					BluetoothValue.INSTANCE.setConnectStatus(BluetoothConstants.STATUS_UNCONNECTED);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					mBluetoothSocket=null;
					BluetoothValue.INSTANCE.setConnectStatus(BluetoothConstants.STATUS_UNCONNECTED);
				}
			}			
			
			BluetoothValue.INSTANCE.disConnecting=false;//正在停止连接为false
			
			BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
			adapter.disable();
			
			//断开蓝牙成功
			Message msg=mHandler.obtainMessage();
			msg.what=BluetoothConstants.MESSAGE_DISCONNECT_SUCCESS;
			msg.sendToTarget();
		}
		
	}
	
	
	
	/**
	 * 
	
	* @ClassName: ReceiveThread 
	
	* @Description: TODO(接收线程) 
	
	* @author sunshineHu hucx@itouch.com.cn
	
	* @date 2015年1月15日 下午1:53:53 
	
	*
	 */
	class ReceiveThread extends Thread{

		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			//如果设置中蓝牙开关打开，就一直保持接收线程
			while(BluetoothValue.INSTANCE.isBluetoothStatus()&&mBluetoothSocket!=null){
				InputStream is = null;
				try {
					is=mBluetoothSocket.getInputStream();
					byte[] buffer=new byte[bufferSize];//
					int len=0;
					while((len=is.read(buffer))!=-1){
						if(len==0||len>bufferSize){
							continue;
						}
						byte[] content=new byte[len];
						System.arraycopy(buffer, 0, content, 0, len);
						/*BluetoothPacket packet=new BluetoothPacket();
						packet.setRaw(content);*/
						//交给处理中心
						Message msg=mHandler.obtainMessage(BluetoothConstants.DATA_RECEIVE);
						msg.obj=content;
						msg.sendToTarget();
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					try {
						if(is!=null)
						is.close();
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					BluetoothValue.INSTANCE.setConnectStatus(BluetoothConstants.STATUS_UNCONNECTED);//连接错误
					Message msg=mHandler.obtainMessage(BluetoothConstants.RECEIVE_ERROR);
					msg.sendToTarget();

					synchronized (statusMutext) {
						
						statusMutext.notify();
					
					}
					
					//log
					Log.e("BluetoothReceive exception", e.getMessage());
				}
			
				
				/*//连接断开后线程休眠100ms
				try {
					sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}*/
				
				synchronized (readMutext) {
					
					
					try {
						readMutext.wait(10*1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				
				}
				
			}
		}
		
	}
	
	
	
	
	/**
	 * 
	 * 发送数据线程
	 * 新增
	 * 
	 */
	class SendThread extends Thread{

		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			//如果socket 不为空，开启发送线程
			while(BluetoothValue.INSTANCE.isBluetoothStatus()&&mBluetoothSocket!=null){
				
				try {
					
					if(BluetoothValue.INSTANCE.packetQueue.size()!=0){
						//处于已连接状态
						if(BluetoothValue.INSTANCE.getConnectStatus()==BluetoothConstants.STATUS_CONNECTED){
							//休眠1s
							sleep(1000);
							
							if(BluetoothValue.INSTANCE.getConnectStatus()==BluetoothConstants.STATUS_CONNECTED){
								
								OutputStream os;
								//从阻塞队列中取出数据
								BluetoothPacket packet=BluetoothValue.INSTANCE.packetQueue.poll(10, TimeUnit.MILLISECONDS);
								
								try {
									os = mBluetoothSocket.getOutputStream();
									
									if(os!=null&&BluetoothValue.INSTANCE.getConnectStatus()==BluetoothConstants.STATUS_CONNECTED){
										if(packet!=null){
											os.write(packet.getRaw());
										}
									}
								} catch (Exception e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
									//出现异常重新加入队列
									BluetoothValue.INSTANCE.packetQueue.add(packet);
								}
							
							}
						}
					}else{
						//sleep(1000);//如果队列为空，休眠100ms继续检查
						synchronized (writeMutext) {
						
							writeMutext.wait(30*1000);
						
						}
					}	
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
		}
		
	}
	
	
	/***
	 * 
	 * 检查蓝牙连接状态线程
	 * 
	 * 
	 */
	
	class CheckThread extends Thread{

		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			
			//10s后开始检测
			try {
				sleep(10000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			//蓝牙开关打开就开始检测
			while(BluetoothValue.INSTANCE.isBluetoothStatus()){
				
				
				if(BluetoothValue.INSTANCE.getConnectStatus()!=BluetoothConstants.STATUS_UNCONNECTED){
					
					//如果已经连上wait
					synchronized (statusMutext) {
						
						try {
							statusMutext.wait(10*1000);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}

					}
					
				}
				
				
				//检查蓝牙状态，如果蓝牙被关闭就不再打开了
				BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
				if(!adapter.isEnabled()){
					BluetoothValue.INSTANCE.setBluetoothStatus(false);
					BluetoothValue.INSTANCE.setConnectStatus(BluetoothConstants.STATUS_UNCONNECTED);
				}
				
				if(device!=null){

					if(device.getBondState()==BluetoothDevice.BOND_NONE){
						try {
							sleep(30000);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					
					if(BluetoothValue.INSTANCE.getConnectStatus()==BluetoothConstants.STATUS_UNCONNECTED){
						
						connect(address, mContext);
						
					}
				}
				
			}
		}
		
	}
	
	
	
	/**
	 * 
	
	* @Title: sendPacket 
	
	* @Description: TODO(发送数据方法，改为加入发送队列) 
	
	* @param @param packet
	* @param @return    设定文件 
	
	* @return boolean    返回类型 
	
	* @throws
	 */
	public boolean sendPacket(BluetoothPacket packet){
		//如果队列已满会返回false
		if(BluetoothValue.INSTANCE.packetQueue.add(packet)){
			synchronized (writeMutext) {
				writeMutext.notify();
			}
			return true;
		}
		return false;
	
	}
	
	
	
	/***
	 * 发送蓝牙数据包（直接发送）
	 * 自从改成了连断模式后，不推荐
	 */
	@Deprecated
	public boolean sendBluetoothPacket(BluetoothPacket packet){
		
		if(BluetoothValue.INSTANCE.getConnectStatus()==BluetoothConstants.STATUS_CONNECTED){
			try {
				OutputStream os=mBluetoothSocket.getOutputStream();
				os.write(packet.getRaw());
				return true;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return false;
	}
	
}
